package org.game.remote;

import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.bean.ActivityInfo;
import org.bean.DictionariesDTO;
import org.bean.DungeonTeamMember;
import org.bean.FriendInfo;
import org.bean.FunctionSwitchDTO;
import org.bean.InterceptInfoDTO;
import org.bean.NoticeDTO;
import org.bean.PlayerInfo;
import org.bean.SourceChatMsg;
import org.bean.StoreInfo;
import org.cache.DictionariesCache;
import org.cache.FunctionSwitchCache;
import org.cache.InterceptMappingCache;
import org.cfg.DiscreteDataCfg;
import org.cfg.cache.DiscreteDataCfgCache;
import org.constant.ActionEnum;
import org.constant.ChatConstant;
import org.constant.DiscreteDataID;
import org.constant.EventConditionKey;
import org.constant.EventConditionType;
import org.constant.EventType;
import org.constant.FriendConstant;
import org.constant.InterceptConstant;
import org.constant.ItemConstantId;
import org.error.LoginErrorCode;
import org.game.cache.NoticeCache;
import org.game.cache.OnlinePlayerCache;
import org.game.cache.ServerCache;
import org.game.constant.RemoteModuleEnum;
import org.game.db.bean.Player;
import org.game.db.bean.PlayerData;
import org.game.db.cache.PlayerCache;
import org.game.db.proxy.bean.PlayerDataProxy;
import org.game.db.vo.PlayerDataVO.DiscreteVO;
import org.game.log.builder.LogDsp;
import org.game.log.dsp.GoodsDsp;
import org.game.manager.ActivityManager;
import org.game.manager.GMDataManager;
import org.game.manager.GameRechargeManager;
import org.game.manager.GameServerManager;
import org.game.manager.ItemManager;
import org.game.manager.MailManager;
import org.game.manager.NoticeManager;
import org.game.manager.PlayerManager;
import org.game.manager.StoreManager;
import org.game.module.chatbo.ChatBO;
import org.game.module.core.Core;
import org.game.module.friendsbo.FriendsBO;
import org.game.module.storebo.handler.WechatShopHandler;
import org.game.msgBuilder.ChatMsgBuilder;
import org.game.msgBuilder.FriendMsgBuilder;
import org.game.msgBuilder.FunctionSwitchMsgBuilder;
import org.game.plugin.event.GameEvent;
import org.game.plugin.event.GameEventPlugin;
import org.game.protobuf.s2c.S2CChatMsg.ChatInfo;
import org.game.protobuf.s2c.S2CFriendMsg.RespFriends;
import org.game.protobuf.s2c.S2CItemMsg;
import org.game.util.ProtoUnit;
import org.remote.game.RemoteGameServer;
import org.script.ScriptJavaLoader;
import org.utils.ExceptionEx;

import com.dal.gm_api.constant.OperateServerType;
import com.google.common.collect.Maps;
import com.sojoys.artifact.annotation.RemoteServer;
import com.sojoys.artifact.constant.ServerStatusEnum;
import com.sojoys.artifact.constant.SessionStatusEnum;
import com.sojoys.artifact.core.IServer;
import com.sojoys.artifact.exception.AbstractLogicModelException;
import com.sojoys.artifact.factory.message.IMessage;
import com.sojoys.artifact.factory.session.ISession;
import com.sojoys.artifact.manager.MessageManager;
import com.sojoys.artifact.tools.ToolList;
import com.sojoys.artifact.tools.ToolMap;
import com.xiaoleilu.hutool.collection.CollUtil;
import com.xiaoleilu.hutool.date.DateUtil;
import com.xiaoleilu.hutool.log.Log;
import com.xiaoleilu.hutool.log.LogFactory;
import com.xiaoleilu.hutool.util.MapUtil;

import io.netty.channel.ChannelFutureListener;

/**
 * @author : DengYing
 * @CreateDate : 2017年9月7日 下午7:07:25
 * @Description ：Please describe this document
 */
@RemoteServer(RemoteGameServer.class)
public class RemoteGameServerImpl implements RemoteGameServer {

    static final Log log = LogFactory.get(RemoteGameServerImpl.class);

    @Override
    public void loginServerStart() {
        // 注册游戏服务器
        GameServerManager.me().registerGameServerInfo();
    }

    @Override
    public void socialServerStart() {}


    @Override
    public void notifyChat(SourceChatMsg msg, Set<Integer> targetPids)
            throws AbstractLogicModelException {
        // 聊天消息封装
        // ChatInfo.Builder chatInfoBuilder = ChatInfo.newBuilder();
        // chatInfoBuilder.setChatType(msg.getChatType());
        // chatInfoBuilder.setContent(msg.getContent());
        // chatInfoBuilder.setPid(msg.getSourcePid());
        // chatInfoBuilder.setPname(msg.getSourceName());

        ChatInfo info = ChatMsgBuilder.me().builderChatInfo(msg);
        byte[] bodys = ProtoUnit.toByte(info);
        // 系统消息全服发送
        if (msg.getChannel() == ChatConstant.CHANNEL_SYSTEM) {
            Collection<Player> onlinePlayers = OnlinePlayerCache.getAll();
            for (Player player : onlinePlayers) {
                player.getPlayerProxy().sendMsg(
                        MessageManager.me().create(ChatBO.pushChatMsg, bodys));
            }
        } else {
            for (Integer targetPid : targetPids) {
                Player player = OnlinePlayerCache.getPlayerById(targetPid);
                if (player != null) {
                    player.getPlayerProxy().sendMsg(
                            MessageManager.me().create(ChatBO.pushChatMsg, bodys));
                }
            }
        }

    }

    @Override
    public void fightOver(int pid, int fightResult) {

    }

    @Override
    public byte[] getTargetPlayerInfo(int targetPid) throws AbstractLogicModelException {
        return PlayerManager.me().getLocalTargetPlayerInfo(targetPid);
    }

    @Override
    public void noticeStore(StoreInfo storeInfo) {
        StoreManager.me().receiveStoreInfo(storeInfo);
        RemoteModuleEnum.STORE.setInit(true);
    }

    @Override
    public void syncDynamicCommodity(List<Map> added, List<Map> shelf)
            throws AbstractLogicModelException {

    }


    @Override
    public void notifyFriendInfos(Map<Integer, List<FriendInfo>> info, Map<Object, Object> ext)
            throws AbstractLogicModelException {
        DiscreteDataCfg cfg = DiscreteDataCfgCache.me().getById(DiscreteDataID.FRIEND_CONFIG);
        int friendship = ToolMap.getInt("friendship", cfg.getData(), 1);
        for (Entry<Integer, List<FriendInfo>> e : info.entrySet()) {
            // Player player = OnlinePlayerCache.getPlayerById(e.getKey());
            Player player = PlayerCache.me().getById(e.getKey());
            if (ToolMap.getBoolean("receiveAway", ext, false)) {
                Date lastReceiveTime = ToolMap.getDate("lastReceiveTime", ext, new Date());
                int receiveCount = ToolMap.getInt("receiveCount", ext, 0);

                PlayerData playerData = player.getPlayerDatasFkPlayerId();
                PlayerDataProxy playerDataProxy = playerData.getPlayerDataProxy();
                DiscreteVO discreteVO = playerDataProxy.getDiscreteVO();
                // if (lastReceiveTime.getTime() != discreteVO.getLastGetFriendGiftDate().getTime()
                // && receiveCount != discreteVO.getNowGetFriendGiftCount()) {
                discreteVO.setLastGetFriendGiftDate(lastReceiveTime);
                discreteVO.setNowGetFriendGiftCount(receiveCount);
                playerDataProxy.save();
                // }

                // 发送领取的奖励
                int count = ToolMap.getInt("awayCount", ext, 0) * friendship;
                if (count > 0) {
                    ItemManager.me().addGoodsAndPush(player, null, null,
                            MapUtil.of(ItemConstantId.FRIEND_SHIP_POINT, count),
                            LogDsp.newBuilder(GoodsDsp.RECEIVE_FRIENDS_AWAY));
                }
            }

            int addFriendCount = 0;
            int delFriendCount = 0;
            for (FriendInfo friendInfo : e.getValue()) {
                if (friendInfo.getFriendAction() == FriendConstant.FRIEND_ADD_EVENT) {
                    addFriendCount++;
                }
                if (friendInfo.getFriendAction() == FriendConstant.FRIEND_DEL_EVENT) {
                    addFriendCount++;
                }
            }
            int changeFriendCount = addFriendCount - delFriendCount;
            if (changeFriendCount != 0) {
                Map<String, Object> in = Maps.newHashMap();
                in.put(EventConditionKey.CONDITION_TYPE, EventConditionType.FRIEND_COUNT);
                in.put(EventConditionKey.CHANGE_FRIEND_COUNT, changeFriendCount);
                GameEvent event = new GameEvent(player, EventType.FRIEND, in);
                GameEventPlugin.syncSubmit(event);
            }

            if (player != null) {
                List<FriendInfo> notifyList = e.getValue();
                RespFriends resp = FriendMsgBuilder.createRespFriendsMsg(player, notifyList);
                player.getPlayerProxy().sendMsg(
                        MessageManager.me().create(FriendsBO.getFriends, ProtoUnit.toByte(resp)));
            }
        }
    }

    @Override
    public byte[] getHelpHeroInfo(int playerId, int heroCid) throws AbstractLogicModelException {
        return PlayerManager.me().getLocalHeroInfo(playerId, heroCid);
    }

    @Override
    public void noticeNewMemberJoin(List<Integer> pidList, DungeonTeamMember newMember) {

    }

    @Override
    public void noticeChangeReadyState(List<Integer> pidList, int pid, boolean state) {

    }

    @Override
    public void noticeIntercept(List<InterceptInfoDTO> list) {
        InterceptMappingCache.changeInterceptInfo(list);
        // 如果是封号 & 踢下线
        for (InterceptInfoDTO interceptInfoDTO : list) {
            if (interceptInfoDTO.getType() == InterceptConstant.INTERCEPT_TYPE_ACCOUNT_ID
                    && interceptInfoDTO.getAction() == ActionEnum.ADD) {
                Player player = OnlinePlayerCache.getPlayerByUid(interceptInfoDTO.getTarget());
                if (player!=null) {
                	ISession session = player.getPlayerProxy().getSession();
                    if (session.getStatus() == SessionStatusEnum.RUNNING) {
                        if (player != null && player.getPlayerProxy().isOnline()) {
                            PlayerManager.me().offline(player);
                        }
                        session.setStatus(SessionStatusEnum.CLOSE);
                    }
                    io.netty.channel.Channel channel = session.getChannel();
                    channel.writeAndFlush(
                            MessageManager.me().create(Core.logoutGame,
                                    LoginErrorCode.ACCOUNT_INTERCEPT)).addListener(
                            ChannelFutureListener.CLOSE);
				}
            }
        }
        RemoteModuleEnum.INTERCEPT.setInit(true);
    }


    @Override
    public void noticeSwitch(List<FunctionSwitchDTO> list) {
        FunctionSwitchCache.changeCache(list);
        if (!CollUtil.isEmpty(list)) {
            IMessage msg =
                    MessageManager.me().create(Core.getFunctionSwitch,
                            FunctionSwitchMsgBuilder.buildRespFunctionSwitch(list).toByteArray());
            OnlinePlayerCache.sendMsgByOnlinePlayer(msg);
        }

        RemoteModuleEnum.FUNCTION_SWITCH.setInit(true);
    }

    @Override
    public void noticeActivity(List<ActivityInfo> list) {
        ActivityManager.me().receiveActivity(list);
        RemoteModuleEnum.ACTIVITY.setInit(true);
    }

    @Override
    public void noticeNotice(List<NoticeDTO> noticeList) {
        NoticeCache.addCache(noticeList);
        NoticeManager.broadcastNotice();
    }

    @Override
    public void addNotice(List<NoticeDTO> noticeList) {
        NoticeCache.addCache(noticeList);
        NoticeManager.broadcastNotice();
    }

    @Override
    public void modifyNotice(List<NoticeDTO> noticeList) {
        NoticeCache.modifyCache(noticeList);
        NoticeManager.broadcastNotice();
    }

    @Override
    public void removeNotice(List<Integer> noticeIdList) {
        NoticeCache.removeCache(noticeIdList);
        NoticeManager.broadcastNotice();
    }

    @Override
    public void broadcastMarqueeNotice(List<Integer> noticeIdList) {
        NoticeManager.broadcastMarqueeNotice(noticeIdList);
    }

    @Override
    public void sendGMMail(String uuid, int type, String title, String body,
            Map<Integer, Integer> item, Map bodyParam, List<Integer> playerIdList) {
        MailManager.me().sendGMMail(uuid, type, title, body, item, bodyParam, playerIdList);
    }

    @Override
    public List<String> queryGMMail(int pid, long startTime, long endTime) {
        return MailManager.me().queryGMMail(pid, startTime, endTime);
    }

    @Override
    public void operateServerState(int state) {
        ServerStatusEnum en = null;
        for (ServerStatusEnum e : ServerStatusEnum.values()) {
            if (e.getCode() == state) {
                en = e;
                break;
            }
        }
        if (en != null) {
            IServer.SERVER_STATUS = en;
            log.info("----operateServerState = " + IServer.SERVER_STATUS);
            GameServerManager.me().registerGameServerInfo();
            if(IServer.SERVER_STATUS == ServerStatusEnum.AEGIS){
                // 踢玩家下线
                OnlinePlayerCache.getAll().forEach(p->{
                    p.getPlayerProxy().getSession().close();
                });
            }
        }
    }

    @Override
    public Object getGameData(String className, String methodName, Object id) {
        return GMDataManager.getData(className, methodName, id);
    }

    @Override
    public boolean noticePaymentSuccess(int playerId, String orderId, int goodsId) {
        return GameRechargeManager.deliveryOrderGoods(playerId, orderId, goodsId);
    }

    @Override
    public void newDay(Date date) {
        log.info("************* newDay " + DateUtil.formatDateTime(date));
        ServerCache.newDate = date;
    }

    @Override
    public void noticeDict(List<DictionariesDTO> list) {
        DictionariesCache.changeCache(list);
        RemoteModuleEnum.DICTIONARIES.setInit(true);
    }

    @Override
    public int wechatShopExchange(String orderId, int playerId, int prizeid, int num, int secTime) {
        // 处理微信积分商城礼包兑换 返回结果对应social服WechatShopResult
        log.info("------wechatShopExchange------orderId=" + orderId + " playerId=" + playerId
                + " prizeid=" + prizeid + " num=" + num + " secTime=" + secTime);
        Player player = PlayerCache.me().getById(playerId);
        if (player == null) {
            return 6;// 角色id错误
        }
        try {
            StoreManager.me().buy(player, prizeid, num, WechatShopHandler.me());
        } catch (AbstractLogicModelException e) {
            int code = e.getCode();
            log.error("------wechatShopExchange----errcode=" + code);
            return code;
        } catch (Exception e) {
            log.error(ExceptionEx.e2s(e));
            return 7;
        }
        return 0;
    }

    @Override
    public PlayerInfo getPlayerInfo(int pid) {
        org.bean.PlayerInfo playerInfo = ServerCache.getPlayerInfoByPid(pid);
        return playerInfo;
    }

    @Override
    public void reloadScript(String scriptName) {
        Map<String, String> parameters = new HashMap<String, String>();
        if (scriptName != null && !"".equals(scriptName)) {
            parameters.put("file", scriptName);// 默认重载所有脚本，可指定重载单个脚本
        }
        ScriptJavaLoader.getInstance().loadScript(parameters);
    }

    @Override
    public void changeItem(int pid, Map<Integer, Integer> goods, GoodsDsp dsp, boolean add) {
        Player player = PlayerCache.me().getById(pid);
        if (add){
            ItemManager.addGoodsAndPush(player,null,null,goods, LogDsp.newBuilder(dsp));
        }else{
            ItemManager.costGoodsByCid(player,goods,LogDsp.newBuilder(dsp), S2CItemMsg.ItemList.newBuilder());
        }
    }
}
